package GUI.main.dialogs;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.GregorianCalendar;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.table.AbstractTableModel;

import officeserver.log_error.UserException;
import officeserver.report.Appointment;
import officeserver.report.Treatment;
import officeserver.users.AccessLevel;
import officeserver.users.PersonalInfo;

import GUI.calendar.CalendarPanel;
import GUI.helpers.ButtonType;
import GUI.helpers.PButton;
import GUI.helpers.PTextField;
import GUI.helpers.ProjectConstants;
import GUI.helpers.TextFieldType;
import GUI.main.MainClient;

public class InvoiceDialog extends JDialog implements ActionListener {

    private static final long serialVersionUID = 1L;

    private static final int WIDTH = 400;
    private static final int HEIGHT = 550;

    private JPanel titlePanel;

    private JPanel centerPanel;

    private JPanel northCenterPanel;
    private JPanel patientPanel;
    private JLabel patientLabel;
    private PTextField patientField;
    private JPanel doctorPanel;
    private JLabel doctorLabel;
    private PTextField doctorField;

    private JScrollPane tablePane;
    private JTable invoiceItemsTable;

    private JPanel buttonPanel;
    private JButton closeButton;

    private Appointment appointment;
    
    public InvoiceDialog(Appointment appointment) {
	this.appointment = appointment;
	setSize(new Dimension(WIDTH, HEIGHT));
	setDefaultCloseOperation(HIDE_ON_CLOSE);
	final int x = (ProjectConstants.SCREEN_DIM.width - WIDTH) / 2;
	final int y = (ProjectConstants.SCREEN_DIM.height - HEIGHT) / 2;
	setLocation(x, y);
	setLayout(new BorderLayout());

	add(getTitlePanel(), BorderLayout.NORTH);
	add(getCenterPanel(), BorderLayout.CENTER);
	add(getButtonPanel(), BorderLayout.SOUTH);
    }

    /**
     * @return
     */
    private JPanel getTitlePanel() {
	if (titlePanel == null) {
	    titlePanel = new JPanel() {
		private static final long serialVersionUID = 1L;

		public void paintComponent(Graphics g) {
		    super.paintComponent(g);
		    g.setColor(ProjectConstants.SUBHEADER_COLOR);
		    g.fillRect(0, 0, getWidth(), getHeight());
		    g.setColor(Color.white);
		    g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 24));
		    g.drawString("invoice:", 24, getHeight() - 8);
		}
	    };
	    titlePanel.setPreferredSize(new Dimension(WIDTH, ProjectConstants.HEADER_HEIGHT));
	}
	return titlePanel;
    }

    /**
     * @return
     */
    private JPanel getCenterPanel() {
	if (centerPanel == null) {
	    centerPanel = new JPanel();
	    centerPanel.setLayout(new BorderLayout());

	    centerPanel.add(getNorthCenterPanel(), BorderLayout.NORTH);
	    centerPanel.add(getTablePane(), BorderLayout.CENTER);
	}
	return centerPanel;
    }

    /**
     * @return
     */
    private JScrollPane getTablePane() {
	if (tablePane == null) {
	    tablePane = new JScrollPane(getInvoiceItemsTable());
	    tablePane.setBorder(new EmptyBorder(20, 25, 0, 25));
	    tablePane.setPreferredSize(new Dimension(WIDTH, 300));
	}
	return tablePane;
    }

    /**
     * @return
     */
    private JTable getInvoiceItemsTable() {
	if (invoiceItemsTable == null) {
	    invoiceItemsTable = new JTable(new InvoiceTableModel());
	    invoiceItemsTable.setBorder(new LineBorder(ProjectConstants.BORDER_MAIN_COLOR,2));
	    invoiceItemsTable.setGridColor(ProjectConstants.BORDER_SUB_COLOR);
	}
	return invoiceItemsTable;
    }

    /**
     * @return
     */
    private JPanel getNorthCenterPanel() {
	if (northCenterPanel == null) {
	    northCenterPanel = new JPanel();

	    northCenterPanel.setLayout(new BoxLayout(northCenterPanel, BoxLayout.PAGE_AXIS));

	    northCenterPanel.add(getPatientPanel());
	    northCenterPanel.add(getDoctorPanel());
	}
	return northCenterPanel;
    }

    /**
     * @return
     */
    private JPanel getPatientPanel() {
	if (patientPanel == null) {
	    patientPanel = new JPanel();

	    patientPanel.setLayout(new BorderLayout());
	    patientPanel.setBorder(new EmptyBorder(10, 10, 0, 10));

	    patientLabel = new JLabel(ProjectConstants.CELLPAD + "first name:");
	    patientLabel.setPreferredSize(new Dimension(ProjectConstants.LABEL_WIDTH, 25));

	    patientPanel.add(patientLabel, BorderLayout.WEST);
	    patientPanel.add(getPatientField(), BorderLayout.EAST);
	}
	return patientPanel;
    }

    /**
     * @return
     */
    private PTextField getPatientField() {
	if (patientField == null) {
	    try {
		MainClient.getConnection().userSearch(
			appointment.getPatientID(), AccessLevel.PATIENT);
	    } catch (UserException e) {
		e.printStackTrace();
	    }
	    PersonalInfo pInfo = null;
	    try {
		pInfo = MainClient.getConnection().getSearchPersonalInfo();
	    } catch (UserException e) {
		e.printStackTrace();
	    }
	    patientField = new PTextField(pInfo.getFirstName() + " "
		    + pInfo.getLastName(), TextFieldType.LONG);
	    patientField.setEditable(false);
	}
	return patientField;
    }

    /**
     * @return
     */
    private JPanel getDoctorPanel() {
	if (doctorPanel == null) {
	    doctorPanel = new JPanel();

	    doctorPanel.setLayout(new BorderLayout());
	    doctorPanel.setBorder(new EmptyBorder(10, 10, 10, 10));

	    doctorLabel = new JLabel(ProjectConstants.CELLPAD + "doctor:");
	    doctorLabel.setPreferredSize(new Dimension(ProjectConstants.LABEL_WIDTH, 25));

	    doctorPanel.add(doctorLabel, BorderLayout.WEST);
	    doctorPanel.add(getDoctorField(), BorderLayout.EAST);
	}
	return doctorPanel;
    }

    /**
     * @return
     */
    private PTextField getDoctorField() {
	if (doctorField == null) {
	    try {
		MainClient.getConnection().userSearch(
			appointment.getDoctorID(), AccessLevel.DOCTOR);
	    } catch (UserException e) {
		e.printStackTrace();
	    }
	    PersonalInfo pInfo = null;
	    try {
		pInfo = MainClient.getConnection().getSearchPersonalInfo();
	    } catch (UserException e) {
		e.printStackTrace();
	    }
	    doctorField = new PTextField(pInfo.getFirstName() + " "
		    + pInfo.getLastName(), TextFieldType.LONG);
	    doctorField.setEditable(false);
	}
	return doctorField;
    }

    /**
     * @return
     */
    private JPanel getButtonPanel() {
	if (buttonPanel == null) {
	    buttonPanel = new JPanel();
	    buttonPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
	    buttonPanel.setLayout(new GridBagLayout());
	    buttonPanel.setPreferredSize(new Dimension(WIDTH, 50));

	    buttonPanel.add(getCloseButton());
	}
	return buttonPanel;
    }

    /**
     * @return
     */
    private JButton getCloseButton() {
	if (closeButton == null) {
	    closeButton = new PButton("Close", ButtonType.MEDIUM);
	    closeButton.addActionListener(this);
	}
	return closeButton;
    }

    public void actionPerformed(ActionEvent evt) {
	if (evt.getSource() == getCloseButton()) {
	    setVisible(false);
	}
    }

    private class InvoiceTableModel extends AbstractTableModel {
	private static final long serialVersionUID = 1L;

	private String[] columnNames = { "Item", "Date", "Cost" };

	public int getColumnCount() {
	    return columnNames.length;
	}

	public int getRowCount() {
	    return appointment.getReport().getTreatments().size() + 1;
	}

	public String getColumnName(int col) {
	    return columnNames[col];
	}

	public Object getValueAt(int row, int col) {
	    if (row == getRowCount() - 1) {
		double total = 0;
		for (Treatment treatment : appointment.getReport().getTreatments()) {
		    total += treatment.getCost();
		}
		switch (col) {
		case 0:
		    return "Total";
		case 2:
		    return String.format("$%.2f", total);
		default:
		    // invalid colum; don't do anything
		    return "";
		}
	    } else {
		Treatment treatment = appointment.getReport().getTreatments().get(row);
		switch (col) {
		case 0:
		    return treatment.getType();
		case 1:
		    appointment.getDay();
		    GregorianCalendar gc = new GregorianCalendar(2011, 0, 1);
		    gc.roll(Calendar.DAY_OF_YEAR, appointment.getDay());
		    StringBuilder builder = new StringBuilder();
		    builder.append(CalendarPanel.getMonthMap().get(
			    gc.get(Calendar.MONTH)));
		    builder.append(" ");
		    builder.append(gc.get(Calendar.DAY_OF_MONTH));
		    builder.append(", ");
		    builder.append(gc.get(Calendar.YEAR));
		    return builder.toString();
		case 2:
		    return String.format("$%.2f", treatment.getCost());
		default:
		    // invalid colum; don't do anything
		    return "";
		}
	    }
	}
    }
}
